@node Accessing Scheme data from C
@section Accessing Scheme data from C

@c No better place to put s48_value's index entry.
@bnindex s48_value
@cindex @file{scheme48.h}
The C header file @file{scheme48.h} provides access to Scheme48 data
structures.  The type @code{s48_value} is used for Scheme values.  When
the type of a value is known, such as the integer returned by the
Scheme procedure @code{vector-length} or the boolean returned by
@code{pair}, the corresponding C function returns a C value of the
appropriate type, not an @code{s48_value}.  Predicates return @code{1}
for true and @code{0} for false.

@cindex Scheme constants in C
@cindex C macros for Scheme constants
@deftypevr {C macro} s48_value S48_FALSE
@deftypevrx {C macro} s48_value S48_TRUE
@deftypevrx {C macro} s48_value S48_NULL
@deftypevrx {C macro} s48_value S48_UNSPECIFIC
@deftypevrx {C macro} s48_value S48_EOF
@deftypevrx {C macro} long S48_MAX_FIXNUM_VALUE
@deftypevrx {C macro} long S48_MIN_FIXNUM_VALUE
These C macros denote various Scheme constants.  @code{S48_FALSE} is
the boolean false value, written in Scheme as @code{#f}.
@code{S48_TRUE} is the boolean true value, or @code{#t}.
@code{S48_NULL} is the empty list @code{()}.  @code{S48_UNSPECIFIC} is
a miscellaneous value returned by procedures that have no meaningful
return value (accessed in Scheme48 by the nullary procedure
@code{unspecific} in the @code{util} structure).  @code{S48_EOF} is
the end-of-file object (which the Scheme procedure @code{eof-object?}
answers true for).  @code{S48_MAX_FIXNUM_VALUE} is the maximum integer
as a @code{long} that can be represented in a Scheme48 fixnum.
@code{S48_MIN_FIXNUM_VALUE} is similar, but the minimum integer.
@end deftypevr

@cindex C and Scheme data conversion
@cindex Scheme and C data conversion
@deftypefn {C macro} int S48_EXTRACT_BOOLEAN (s48_value @var{boolean})
@deftypefnx {C function} {unsigned char} s48_extract_char (s48_value @var{char})
@deftypefnx {C function} {char *} s48_extract_string (s48_value @var{string})
@deftypefnx {C function} {char *} s48_extract_byte_vector (s48_value @var{bytev})
@deftypefnx {C function} long s48_extract_integer (s48_value @var{integer})
@deftypefnx {C function} double s48_extract_double (s48_value @var{double})
@deftypefnx {C macro} s48_value S48_ENTER_BOOLEAN (int @var{boolean})
@deftypefnx {C function} s48_value s48_enter_char (unsigned char @var{char})
@deftypefnx {C function} s48_value s48_enter_string (char *@var{string})
@deftypefnx {C function} s48_value s48_enter_byte_vector (char *@var{bytev}, long @var{length})
@deftypefnx {C function} s48_value s48_enter_integer (long @var{integer})
@deftypefnx {C function} s48_value s48_enter_double (double @var{double})
These functions & macros convert values between their respective Scheme
& C representations.

@code{S48_EXTRACT_BOOLEAN} returns @code{0} if @var{boolean} is
@code{#f} and @code{1} otherwise.  @code{S48_ENTER_BOOLEAN} returns the
Scheme value @code{#f} if its argument is zero and @code{#t} otherwise.

@code{s48_extract_char} & @code{s48_enter_char} convert between Scheme
characters and C @code{char}s.

@code{s48_extract_string} & @code{s48_extract_byte_vector} return
pointers to the actual storage used by @var{string} or @var{bytev}.
These pointers are valid only until the next garbage collection,
however; @pxref{Interacting with the Scheme heap in C}.
@code{s48_enter_string} & @code{s48_enter_byte_vector} allocate
space on the Scheme48 heap for the given strings or byte vectors.
@code{s48_enter_string} copies the data starting from the pointer it
is given up to the first ASCII @code{NUL} character, whereas
@code{s48_enter_byte_vector} is given the number of bytes to copy into
the Scheme heap.

@code{s48_extract_integer} returns a C @code{long} that represents the
Scheme integer as input.  If the Scheme integer is too large to be
represented in a long, an exception is signalled.  (The Scheme integer
may be a fixnum or a bignum.)  @code{s48_enter_integer} converts back
to Scheme integers, and it will never signal an exception.

@code{s48_extract_double} & @code{s48_enter_double} convert between
Scheme & C double-precision floating point representations.

Of these, @code{s48_enter_string}, @code{s48_enter_byte_vector},
@code{s48_enter_integer}, & @code{s48_enter_double} may cause the
garbage collector to be invoked: the former two copy the string or
byte vector onto the Scheme heap first, @code{s48_enter_integer} may
need to allocate a bignum (since C @code{long}s are wider than Scheme48
fixnums), and floats are heap-allocated in Scheme48.
@end deftypefn

@cindex Scheme boolean testing in C
@cindex C macros on Scheme booleans
@deftypefn {C macro} int S48_TRUE_P (s48_value @var{object})
@deftypefnx {C macro} int S48_FALSE_P (s48_value @var{object})
@code{S48_TRUE_P} returns true if @var{object} is the true constant
@code{S48_TRUE} and false if otherwise.  @code{S48_FALSE_P} returns
true if its argument is the false constant @code{S48_FALSE} and false
if otherwise.
@end deftypefn

@cindex Scheme fixnums from C
@cindex C access to Scheme fixnums
@deftypefn {C macro} int S48_FIXNUM_P (s48_value @var{object})
@deftypefnx {C function} long s48_extract_fixnum (s48_value @var{fixnum})
@deftypefnx {C function} s48_value s48_enter_fixnum (long @var{integer})
@code{S48_FIXNUM_P} is the C predicate for Scheme48 fixnums, delimited
in range by @code{S48_MIN_FIXNUM_VALUE} & @code{S48_MAX_FIXNUM_VALUE}.
@code{s48_extract_fixnum} returns the C @code{long} representation of
the Scheme fixnum, and @code{s48_enter_fixnum} returns the Scheme
fixnum representation of the C @code{long}.  These are identical to
@code{s48_extract_integer} & @code{s48_enter_integer}, except that
@code{s48_extract_fixnum} will never raise a range exception, but
@code{s48_enter_fixnum} may, and @code{s48_enter_fixnum} will never
return a bignum; this is due to the fact that C @code{long}s have a
wider range than Scheme48 fixnums.
@end deftypefn

@cindex Scheme data predicates in C
@cindex C predicates for Scheme data
@deftypefn {C macro} int S48_EQ_P (s48_value @var{a}, s48_value @var{b})
@deftypefnx {C macro} int S48_CHAR_P (s48_value @var{object})
@deftypefnx {C macro} int S48_PAIR_P (s48_value @var{object})
@deftypefnx {C macro} int S48_VECTOR_P (s48_value @var{object})
@deftypefnx {C macro} int S48_STRING_P (s48_value @var{object})
@deftypefnx {C macro} int S48_SYMBOL_P (s48_value @var{object})
@deftypefnx {C macro} int S48_BYTE_VECTOR_P (s48_value @var{object})
@cindex Scheme pair operations in C
@cindex C access to Scheme pairs
@deftypefnx {C macro} s48_value S48_CAR (s48_value @var{pair})
@deftypefnx {C macro} s48_value S48_CDR (s48_value @var{pair})
@deftypefnx {C macro} void S48_SET_CAR (s48_value @var{pair}, s48_value @var{object})
@deftypefnx {C macro} void S48_SET_CDR (s48_value @var{pair}, s48_value @var{object})
@deftypefnx {C function (may GC)} s48_value s48_cons (s48_value @var{car}, s48_value @var{cdr})
@deftypefnx {C function} s48_value s48_length (s48_value @var{list})
@cindex Scheme vector operations in C
@cindex C access to Scheme vectors
@deftypefnx {C macro} long S48_VECTOR_LENGTH (s48_value @var{vector})
@deftypefnx {C macro} s48_value S48_VECTOR_REF (s48_value @var{vector}, long @var{index})
@deftypefnx {C macro} void S48_VECTOR_SET (s48_value @var{vector}, long @var{index}, s48_value @var{object})
@deftypefnx {C function (may GC)} s48_value s48_make_vector (long @var{length}, s48_value @var{fill})
@cindex Scheme string operations in C
@cindex C access to Scheme strings
@deftypefnx {C macro} long S48_STRING_LENGTH (s48_value @var{string})
@deftypefnx {C macro} char S48_STRING_REF (s48_value @var{string}, long @var{index})
@deftypefnx {C macro} void S48_STRING_SET (s48_value @var{string}, long @var{index}, char @var{char})
@deftypefnx {C function (may GC)} s48_value s48_make_string (long @var{length}, char @var{fill})
@deftypefnx {C macro} s48_value S48_SYMBOL_TO_STRING (s48_value @var{symbol})
@cindex Scheme byte vector operations in C
@cindex C access to Scheme byte vectors
@deftypefnx {C macro} long S48_BYTE_VECTOR_LENGTH (s48_value @var{bytev})
@deftypefnx {C macro} char S48_BYTE_VECTOR_REF (s48_value @var{bytev}, long @var{index})
@deftypefnx {C macro} void S48_BYTE_VECTOR_SET (s48_value @var{bytev}, long @var{index}, char @var{byte})
@deftypefnx {C function (may GC)} s48_value s48_make_byte_vector (long @var{length})
C versions of miscellaneous Scheme procedures.  The names were derived
from their Scheme counterparts by replacing hyphens with underscores,
@code{?} suffixes with @code{_P}, and dropping @code{!} suffixes.
@end deftypefn

@node Calling Scheme procedures from C
@section Calling Scheme procedures from C

@cindex Scheme callbacks in C
@deftypefn {C function} s48_value s48_call_scheme (s48_value @var{proc}, long @var{nargs}, ...)
Calls the Scheme procedure @var{proc} on @var{nargs} arguments, which
are passed as additional arguments to @code{s48_call_scheme}.  There
may be at most twelve arguments.  The value returned by the Scheme
procedure is returned to the C procedure.  Calling any Scheme procedure
may potentially cause a garbage collection.
@end deftypefn

@cindex callbacks from C and continuations
@cindex continuations and callbacks from C
@cindex callbacks from C and threads
@cindex threads and callbacks from C
@cindex interaction between continuations and C
There are some complications that arise when mixing calls from C to
Scheme with continuations & threads.  C supports only downward
continuations (via @code{longjmp()}).  Scheme continuations that
capture a portion of the C stack have to follow the same restriction.
For example, suppose Scheme procedure @code{s0} captures continuation
@code{a} and then calls C function @code{c0}, which in turn calls
Scheme procedure @code{s1}.  @code{S1} can safely call the continuation
@code{a}, because that is a downward use.  When @code{a} is called,
Scheme48 will remove the portion of the C stack used by the call to
@code{c0}.  On the other hand, if @code{s1} captures a continuation,
that continuation cannot be used from @code{s0}, because, by the time
control returns to @code{s0}, the C stack used by @code{s0} will no
longer be valid.  An attempt to invoke an upward continuation that is
closed over a portion of the C stack will raise an exception.

In Scheme48, threads are implemented using continuations, so the
downward restriction applies to them as well.  An attempt to return
from Scheme to C at a time when the appropriate C frame is not on the
top of the C stack will cause the current thread to block until the
frame is available.  For example, suppose thread @code{t0} calls a C
function that calls back to Scheme, at which point control switches to
thread @code{t1}, which also calls C & then back to Scheme.  At this
point, both @code{t0} & @code{t1} have active calls to C on the C
stack, with @code{t1}'s C frame above @code{t0}'s.  If @code{t0}
attempts to return from Scheme to C, it will block, because the frame
is not yet accessible.  Once @code{t1} has returned to C and from there
back to Scheme, @code{t0} will be able to resume.  The return to Scheme
is required because context switches can occur only while Scheme code
is running.  @code{T0} will also be able to resume if @code{t1} uses a
continuation to throw past its call out to C.
